package br.com.felix.easyclearcase;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

/**
 * This class represents a file that is under source control, or that will be.
 * */
public class EasyClearCaseFile {
	
	/**
	 * Registry to maintain only one EasyClearCaseFile per file
	 * */
	private static Map<File,EasyClearCaseFile> hsmEasyFiles = new HashMap<File,EasyClearCaseFile>();

	/**
	 * Enumerates possible clearcase statuses.
	 * */
	public enum ClearCaseStatus {
		/**
		 * ClearCase status was not consulted yet.
		 * */
		UNKNOWN,
		/**
		 * File is not under source control.
		 * */
		PRIVATE_FILE, 
		/**
		 * File is under source control but is not checked out.
		 * */
		FILE_ELEMENT,
		/**
		 * File is under source control AND is CHECKED OUT.
		 * */
		CHECKEDOUT;
		
	
		/**
		 * Returns an HTML that gives each status a different color.
		 * */
		public String toString(){
			String color = getColorByStatus(this);
			return "<html><font color='"+color+"'>"+this.name()+"</font></html>";
		}

		
		/**
		 * Gives an HTML color for each status.
		 * @return a valid HTML color String.
		 * */
		public static String getColorByStatus(ClearCaseStatus status) {
			String color = "black";
			switch(status){
				case UNKNOWN:
					color = "gray";
					break;
				case PRIVATE_FILE:
					color = "blue";
					break;
				case FILE_ELEMENT:
					color = "black";
					break;
				case CHECKEDOUT:
					color = "green";
					break;
			}
			return color;
		}

	};
	
	
	/**
	 * The file on the filesystem that this file references.
	 * */
	private File file;
	
	/**
	 * Current status of the file in ClearCase.
	 * */
	private ClearCaseStatus status = ClearCaseStatus.UNKNOWN;
	
	/**
	 * Flag to inform toString to display the absolutePath instead of the name of the file.
	 * */
	private boolean renderAbsolutePath = false;

	
	public boolean isRenderAbsolutePath() {
		return renderAbsolutePath;
	}



	
	public void setRenderAbsolutePath(boolean renderAbsolutePath) {
		this.renderAbsolutePath = renderAbsolutePath;
	}
	
	
	
	public ClearCaseStatus getStatus() {
		return status;
	}



	
	public void setStatus(ClearCaseStatus status) {
		if(status == null){
			status = ClearCaseStatus.UNKNOWN;
		}
		else{
			this.status = status;
		}
	}



	private EasyClearCaseFile(File file) {
		this.file = file;
	}
	
	
	public static EasyClearCaseFile fromFile(File file) {
		EasyClearCaseFile easyfile = hsmEasyFiles.get(file);
		if(easyfile == null){
			easyfile = new EasyClearCaseFile(file);
			hsmEasyFiles.put(file, easyfile);
		}
		return easyfile;
	}
	


	/**
	 * Returns a HTML code with either the file name or the file absolute path.
	 * The HTML has a different color depending on the file Status.
	 * @see EasyClearCaseFile#renderAbsolutePath
	 * */
	public String toString() {
		String color = ClearCaseStatus.getColorByStatus(status);
		if(renderAbsolutePath){
			return "<html><font color='"+color+"'>"+file.getAbsolutePath()+"</font></html>";
		}
		else{
			return "<html><font color='"+color+"'>"+file.getName()+"</font></html>";
		}
	}
	
	
	/**
	 * If this file is a folder, returns a list of child FILES but NOT FOLDERS.
	 * Observe that all EasyClearCaseFiles are newly instantiated, so they have no status information.
	 * @return a list of EasyClearCaseFile, one for each child FILE, but not for FOLDERS.
	 * */
	public EasyClearCaseFile[] listFiles(){
		File[] files = file.listFiles(new java.io.FileFilter() {
			public boolean accept(File pathname) {
				return !pathname.isDirectory();
			}
		});
		EasyClearCaseFile eccfFiles[] = new EasyClearCaseFile[files.length];
		for(int i=0; i<files.length;i++){
			eccfFiles[i] = new EasyClearCaseFile(files[i]);
		}
		return eccfFiles;
	}
	
	
	public String getName(){
		return file.getName();
	}
	
	public String getAbsolutePath(){
		return file.getAbsolutePath();
	}
	
	public long lastModified(){
		return file.lastModified();
	}
	
	public long length(){
		return file.length();
	}


	public File getFile() {
		return file;
	}


	/**
	 * Two EasyClearCaseFiles are equal if they reference the same file.
	 * */
	@Override
	public boolean equals(Object obj) {
		if(!(obj instanceof EasyClearCaseFile)) return false;
		EasyClearCaseFile other = (EasyClearCaseFile)obj;
		return this.file.equals(other.file);
	}
	
	
	public File getParentFile(){
		return file.getParentFile();
	}
	
	
	public EasyClearCaseFile getParentEasyClearCaseFile(){
		return EasyClearCaseFile.fromFile(getParentFile());
	}
	
	
	public boolean isDirectory(){
		return file.isDirectory();
	}




	@Override
	public int hashCode() {
		if(file!=null)return file.hashCode();
		return 0;
	}
}